import pandas as pd
data = pd.read_csv(r"D:\AI\pycharm\数据挖掘\data\Online Retail.csv")
data = data[data['Country'] == "Germany"]
data.dropna(axis=0,subset = ['InvoiceNo'])
data.dropna(axis=0,subset=['StockCode'])
data['InvoiceNo'] = data['InvoiceNo'].astype('str')
data = data[~data['InvoiceNo'].str.contains('C')]

data = data[['InvoiceNo','StockCode']]
invoiceno = data['InvoiceNo'].drop_duplicates().dropna().values.tolist()
data = data.groupby('InvoiceNo')
dataset = []
for i in invoiceno:
    temp = []
    oneinv = data.get_group(i).values.tolist()
    for j in oneinv:
        if j[1] not in temp:
            temp.append(j[1])
    dataset.append(temp)
# print(dataset1)

thread = 25
trust = 0.7


def getlist1():  #获取集合中的元素
    list1 = []
    list11 = []
    for record in dataset:
        for x in record:
            if x not in list1:
                list1.append(x)
    for x in list1:
        list11.append([x])   #为了统一，先转换成集合，因为后面结果的键值都是集合。
    return list11

#x.pop('a') 去除特定元素
def support(listk):
    count = 0
    for record in dataset:
        if set(listk) <= set(record):
            count+=1
    return count
def supportall(listk):   #计算支持度
    dictk = {}
    for x in listk:
        dictk[tuple(x)] = support(x)
    return dictk

def cut(dictk):
    for x in list(dictk.keys()):
        if dictk[x] < thread:   #阈值判断
            dictk.pop(x)   #剪枝
    return dictk

def concat(dictk,k):
    listk = []
    for i in range(len(dictk.keys())):
        for j in range(i+1,len(dictk.keys())):
            temp = list(set(list(dictk.keys())[i]) | set(list(dictk.keys())[j]))  #取并集
            temp_sorted = sorted(temp)   #排序是为了list的相等判断不被顺序干扰
            if (temp_sorted not in listk) and (len(temp_sorted) == k):   #不能重复且数量等于k
                listk.append(temp_sorted)

    return listk  #[[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 3], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6], [4, 5], [4, 6], [5, 6]]

def apriori(result,k,resultfinal):
    '''
        dictk是每次剪枝后的结果
        保存到resultfinal中待取
        如果dictk没有，则返回上一个频繁项集
        如果dictk只有一个，那就返回它作为结果
        否则，就构造k+1项集，并保存到存放未处理的项集result集合中，并返回None
   '''

    dictk = cut(supportall(result[k]))
    resultfinal.append(dictk)
    if len(dictk) == 0 :
        return resultfinal[k-1]

    elif len(dictk) == 1:
        return resultfinal[k]
    else:
        listnext = concat(dictk,k+1)
        result.append(listnext)
        # return supportall(listnext)

if __name__ == '__main__':
    '''
            result: 保存每次合并之后的项集（未计算支持度）
            resultfinal: 保存剪枝后的项集
            k: 项集数
    '''
    result = []
    resultfinal = []
    list0 = [0]
    result.append(list0)
    list1 = getlist1()
    result.append(list1)
    resultfinal.append(list0)
    k = 1

    while (True):
            listresult = apriori(result, k,resultfinal)   #apriori算法
            if listresult!=None:
                print(listresult)
            if(len(resultfinal[k]) <= 1):   #只有一个了就是最后结果
                break
            k = k+1

    # print(resultfinal)
    for k in range(1,len(resultfinal)):
        if(k+1 < len(resultfinal)):
            temp1 = resultfinal[k]
            temp2 = resultfinal[k+1:]
            for sub1 in temp1.keys():
                for sub2 in temp2:
                    for subsub2 in sub2.keys():
                        if(set(sub1) <= set(subsub2)):
                            temptrust = sub2[subsub2] / temp1[sub1]
                            if temptrust > trust:
                                print("{}和{}是强规则,置信度为{}".format(sub1,subsub2,temptrust))




































